package io.esirong.widget.media;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.BlurMaskFilter;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.MaskFilter;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.LinearInterpolator;

/**
 * 录制视频的按钮,长按录制,点击拍照
 * 提供完所的处理操作
 */
public class CaptureButton extends View {
    public final String TAG = CaptureButton.class.getSimpleName();

    private final Paint mPaint;
    private final Context mContext;

    private float btn_center_Y;
    private float btn_center_X;

    private float btn_inside_radius;
    private float btn_outside_radius;
    //before radius
    private float btn_before_inside_radius;
    private float btn_before_outside_radius;
    //after radius
    private float btn_after_inside_radius;
    private float btn_after_outside_radius;

    private float btn_left_X, btn_right_X, btn_result_radius;

    private final int COLOR_BG_ON_IDLE = 0x55EEEEEE;
    private final int COLOR_BTN_ON_BROWSE = 0x66040910;
    private int btn_inside_color = Color.WHITE;
    private int btn_outside_color = 0xFF358BFF;
    private int btn_progress_stroke_color = 0xFF358BFF;

    //记录点击时间，处理快速点击
    private long lastTimeOnClick = -1L;

    //state
    private int STATE_SELECTED;
    private Integer STATE_PENDING;       //动画的中间态 待动画完成后确认值
    private boolean STATE_Anim_playing;       //动画的中间态
    private final int STATE_IDLE = 0;     //空闲状态
    private final int STATE_KEY_DOWN = 1;
    private final int STATE_CAPTURED = 2;
    private final int STATE_RECORD = 3;
    private final int STATE_PICTURE_BROWSE = 4;     //拍照完成后的预览状态
    private final int STATE_RECORD_BROWSE = 5;     //录像完成后的预览状态
    private final int STATE_READY_QUIT = 6;        //退出
    private final int STATE_RECORDED = 7;
    private final int STATE_Anim_Recode = 8;

    private float key_down_Y;
    private long durationAnim = 1_000L;

    private final RectF rectF = new RectF();
    private float progress = 0;
    private LongPressRunnable longPressRunnable = new LongPressRunnable();
    private RecordRunnable recordRunnable = new RecordRunnable();
    private final ValueAnimator record_anim = ValueAnimator.ofFloat(0, 360);
    private CaptureListener mCaptureListener;

    public CaptureButton(Context context) {
        this(context, null);
    }

    public CaptureButton(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public CaptureButton(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mContext = context;
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        STATE_SELECTED = STATE_IDLE;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int width = widthSize;
        Log.i(TAG, "measureWidth = " + width);
        int height = (width / 9) * 4;
        setMeasuredDimension(width, height);
    }

    /**
     * 把密度转换为像素
     */
    public static int dp2px(Context context, float dipValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dipValue * scale + 0.5);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);

        btn_center_X = getWidth() / 2f;
        btn_center_Y = getHeight() / 2f;
        //取短值做半径(关于大小的设计，按钮最小64DP）
        int min = Math.min(getWidth(), getHeight()) / 2;
        int required = dp2px(getContext(), 64);//要求大小64dp
        if (required < min) {
            min = required;
        }
        btn_outside_radius = (float) (min / 1.75);
        btn_inside_radius = (float) (btn_outside_radius * 0.75);

        btn_before_outside_radius = (float) (min / 1.75);
        btn_before_inside_radius = (float) (btn_outside_radius * 0.75);
        btn_after_outside_radius = (float) (min / 1.75);
        btn_after_inside_radius = (float) (btn_outside_radius * 0.6);

        btn_result_radius = (float) (btn_inside_radius);
        btn_left_X = getWidth() >> 1;
        btn_right_X = getWidth() >> 1;
    }

    MaskFilter maskFilter = new BlurMaskFilter(10, BlurMaskFilter.Blur.INNER);
    final Paint paintArc = new Paint();


    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (STATE_SELECTED == STATE_IDLE || STATE_SELECTED == STATE_RECORD) {
            //draw capture button
            mPaint.setColor(btn_inside_color);
            mPaint.setMaskFilter(maskFilter);
            mPaint.setAntiAlias(true);

            float strokeWidth = (float) dp2px(mContext, 4) - dp2px(mContext, 1);
            mPaint.setStrokeWidth(strokeWidth);
            float r_out_circle = btn_before_inside_radius + strokeWidth + dp2px(mContext, 1);
            if (STATE_SELECTED == STATE_IDLE) {
                mPaint.setStyle(Paint.Style.STROKE);
            } else {
                mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
            }

            canvas.drawCircle(btn_center_X, btn_center_Y, r_out_circle, mPaint);

            //
            mPaint.setMaskFilter(null);
            mPaint.setStyle(Paint.Style.FILL);
            mPaint.setColor(btn_outside_color);
            canvas.drawCircle(btn_center_X, btn_center_Y, btn_inside_radius, mPaint);

            //draw Progress bar
            paintArc.setAntiAlias(true);
            paintArc.setColor(btn_progress_stroke_color);
            paintArc.setStyle(Paint.Style.STROKE);
            paintArc.setStrokeWidth(dp2px(mContext, 1));
            //#获取给制范围半径等，更新进度(左上右下)
            rectF.left = btn_center_X - (r_out_circle + dp2px(mContext, 1));
            rectF.top = btn_center_Y - (r_out_circle + dp2px(mContext, 1));
            rectF.right = btn_center_X + (r_out_circle + dp2px(mContext, 1));
            rectF.bottom = btn_center_Y + (r_out_circle + dp2px(mContext, 1));
            canvas.drawArc(rectF, -90, progress, false, paintArc);
            //计算baseline
            Paint textPaint = new Paint();
            textPaint.setStyle(Paint.Style.FILL);
            textPaint.setAntiAlias(true);
            textPaint.setColor(btn_progress_stroke_color);
            textPaint.setStrokeWidth(8);
            textPaint.setTextSize(dp2px(mContext, 14));
            textPaint.setTextAlign(Paint.Align.CENTER);
            Paint.FontMetrics fontMetrics = textPaint.getFontMetrics();

            float distance = (fontMetrics.bottom - fontMetrics.top) / 2 - fontMetrics.bottom;
            float baseline = rectF.centerY() + distance;
            canvas.drawText(remindText, rectF.centerX(), baseline, textPaint);

        } else if (STATE_SELECTED == STATE_RECORD_BROWSE || STATE_SELECTED == STATE_PICTURE_BROWSE) {
            //拍摄，录制结束时

            mPaint.setColor(COLOR_BTN_ON_BROWSE);
            canvas.drawCircle(btn_left_X, btn_center_Y, btn_result_radius, mPaint);
            mPaint.setColor(COLOR_BTN_ON_BROWSE);
            canvas.drawCircle(btn_right_X, btn_center_Y, btn_result_radius, mPaint);

            //left button 图案（返回）
            Paint paint = new Paint();
            paint.setAntiAlias(true);
            paint.setColor(Color.BLACK);
            paint.setStyle(Paint.Style.STROKE);
            paint.setStrokeWidth(3);


            Path path = new Path();
            path.moveTo(btn_left_X - 2, btn_center_Y + 14);
            path.lineTo(btn_left_X + 14, btn_center_Y + 14);
            path.arcTo(new RectF(btn_left_X, btn_center_Y - 14, btn_left_X + 28, btn_center_Y + 14), 90, -180);
            path.lineTo(btn_left_X - 14, btn_center_Y - 14);
            canvas.drawPath(path, paint);

            //Right 右边按钮图案（对勾）
            paint.setStyle(Paint.Style.FILL);
            path.reset();
            path.moveTo(btn_left_X - 14, btn_center_Y - 22);
            path.lineTo(btn_left_X - 14, btn_center_Y - 6);
            path.lineTo(btn_left_X - 23, btn_center_Y - 14);
            path.close();
            canvas.drawPath(path, paint);


            paint.setStyle(Paint.Style.STROKE);
            paint.setColor(0xFF00CC00);
            paint.setStrokeWidth(4);
            path.reset();
            path.moveTo(btn_right_X - 28, btn_center_Y);
            path.lineTo(btn_right_X - 8, btn_center_Y + 22);
            path.lineTo(btn_right_X + 30, btn_center_Y - 20);
            path.lineTo(btn_right_X - 8, btn_center_Y + 18);
            path.close();
            canvas.drawPath(path, paint);

            //动画停止时

            Paint textPaint = new Paint();
            textPaint.setStyle(Paint.Style.FILL);
            textPaint.setAntiAlias(true);
            textPaint.setColor(Color.WHITE);
            textPaint.setStrokeWidth(8);
            textPaint.setTextSize(dp2px(mContext, 14));
            textPaint.setTextAlign(Paint.Align.CENTER);

            //计算baseline
            RectF rectText = new RectF();
            rectText.left = btn_left_X - btn_result_radius;
            rectText.top = btn_center_Y + btn_result_radius;
            rectText.right = btn_left_X + btn_result_radius;

            Paint.FontMetrics fontMetrics = textPaint.getFontMetrics();
            rectText.bottom = btn_center_Y + btn_result_radius + fontMetrics.bottom - fontMetrics.top;

            float distance = (fontMetrics.bottom - fontMetrics.top) / 2 - fontMetrics.bottom;
            float baseline = rectText.centerY() + distance;
            canvas.drawText("重新拍摄", rectText.centerX(), baseline, textPaint);

            //计算baseline
            rectText.left = btn_right_X - btn_result_radius;
            rectText.top = btn_center_Y + btn_result_radius;
            rectText.right = btn_right_X + btn_result_radius;

            rectText.bottom = btn_center_Y + btn_result_radius + fontMetrics.bottom - fontMetrics.top;
            canvas.drawText("确认", rectText.centerX(), baseline, textPaint);
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                //处理快速点

                if (STATE_SELECTED == STATE_IDLE) {
                    if (eventOnBtn(event) && event.getPointerCount() == 1) {
                        key_down_Y = event.getY();
                        return true;
                    }
                } else if (STATE_SELECTED == STATE_RECORD) {
                    //正在录制中
                    if (eventOnBtn(event) && event.getPointerCount() == 1) {
                        return true;
                    }
                } else if (STATE_SELECTED == STATE_RECORD_BROWSE) {
                    if (eventOnBtn2(event) && event.getPointerCount() == 1) {
                        return true;
                    }
                    if (eventOnBtn3(event) && event.getPointerCount() == 1) {
                        return true;
                    }
                } else if (STATE_SELECTED == STATE_PICTURE_BROWSE) {
                    if (eventOnBtn2(event) && event.getPointerCount() == 1) {
                        return true;
                    }
                    if (eventOnBtn3(event) && event.getPointerCount() == 1) {
                        return true;
                    }
                }
                break;
            case MotionEvent.ACTION_MOVE:
                //...
                break;
            case MotionEvent.ACTION_UP:
                //判断长按，忽略点击
                if (STATE_SELECTED == STATE_IDLE) {
                    if (eventOnBtn(event)) {
                        onStartToRecord();
                    }
                } else if (STATE_SELECTED == STATE_KEY_DOWN) {
                    if (eventOnBtn(event)) {
                        onStartToRecord();
                    }
                } else if (STATE_SELECTED == STATE_RECORD) {
                    if (eventOnBtn(event)) {
                        //正在录制时被点击
                        onStopToRecord();
                    }
                } else if (STATE_SELECTED == STATE_RECORD_BROWSE && !STATE_Anim_playing) {
                    if (eventOnBtn2(event)) {
                        onBtnResetClick2();
                    }
                    if (eventOnBtn3(event)) {
                        onBtnConfirmClick3();
                    }
                } else if (STATE_SELECTED == STATE_PICTURE_BROWSE && !STATE_Anim_playing) {
                    if (eventOnBtn2(event)) {
                        onBtnResetClick2();
                    }
                    if (eventOnBtn3(event)) {
                        onBtnConfirmClick3();
                    }
                }
                break;

            default:
                break;


        }
        return false;

    }

    private boolean eventOnBtn(MotionEvent event) {
        boolean on = event.getY() > btn_center_Y - btn_outside_radius
                && event.getY() < btn_center_Y + btn_outside_radius
                && event.getX() > btn_center_X - btn_outside_radius
                && event.getX() < btn_center_X + btn_outside_radius;

        return on;
    }

    private boolean eventOnBtn2(MotionEvent event) {
        //左上右下
        boolean on = event.getX() > btn_left_X - btn_result_radius
                && event.getY() < btn_center_Y + btn_result_radius
                && event.getX() < btn_left_X + btn_result_radius
                && event.getY() > btn_center_Y - btn_result_radius;
        return on;
    }

    private boolean eventOnBtn3(MotionEvent event) {
        //左上右下
        boolean on = event.getX() > btn_right_X - btn_result_radius
                && event.getY() < btn_center_Y + btn_result_radius
                && event.getX() < btn_right_X + btn_result_radius
                && event.getY() > btn_center_Y - btn_result_radius;
        return on;
    }

    private void onStopToRecord() {
        //处理快速点的情况
        long now = System.currentTimeMillis();
        if (now - lastTimeOnClick < 200) {
            return;
        }
        lastTimeOnClick = now;
        Log.w(TAG, "点击=停止录制时");
        stopRecordAnim();
        onStopOnRecord();

        if (mCaptureListener != null) {
            mCaptureListener.record();
        }
    }


    private void onStartToRecord() {
        //处理快速点的情况
        long now = System.currentTimeMillis();
        if (now - lastTimeOnClick < 200) {
            return;
        }
        lastTimeOnClick = now;
        //改变态，初始动画
        Log.w(TAG, "点击=开始录制时");
        post(this::startRecordAnim);
        onStartOnRecord();
        if (mCaptureListener != null) {
            mCaptureListener.recordEnd();
        }
    }

    private void startRecordAnim() {
        startRecordingAnimation();
        if (record_anim != null) {
            record_anim.start();
        }
    }

    private void stopRecordAnim() {

        if (record_anim != null) {
            record_anim.end();
            record_anim.cancel();
        }
    }

    private void onStartOnRecord() {
        STATE_SELECTED = STATE_RECORD;
    }

    private void onStopOnRecord() {
        btn_inside_color = Color.WHITE;
        btn_outside_color = 0xFF358BFF;
        btn_inside_radius = btn_before_inside_radius;
        if (STATE_SELECTED == STATE_RECORD) {
            STATE_SELECTED = STATE_RECORD_BROWSE;
            progress = 0;
            invalidate();
            captureSuccess();

            if (mCaptureListener != null) {
                mCaptureListener.record();
                mCaptureListener.recordEnd();
            }
        }

    }

    private void onBtnResetClick2() {
        Log.w(TAG, "点击onBtnResetClick2");
        captureReset();
        if (mCaptureListener != null) {
            mCaptureListener.cancel();
        }

    }

    private void onBtnConfirmClick3() {
        Log.w(TAG, "点击onBtnConfirmClick3");
        captureReset();
        if (mCaptureListener != null) {
            mCaptureListener.getRecordResult();
        }
        initButton();
    }

    public void initButton() {
        STATE_SELECTED = STATE_IDLE;
        btn_inside_color = Color.WHITE;
        btn_outside_color = 0xFF358BFF;
        invalidate();
    }

    /**
     * 设置可以自动录制的时长
     */
    public void setRecodeDuration(long timeOnRecordDuration) {
        durationAnim = timeOnRecordDuration;
    }

    public void captureSuccess() {
        STATE_PENDING = STATE_SELECTED;
        float l = btn_center_X - btn_inside_radius * 2;
        float r = btn_center_X + btn_inside_radius * 2;

        captureAnimation(l, r);
    }

    /**
     * 恢复
     */
    public void captureReset() {
        STATE_PENDING = STATE_IDLE;
        captureAnimation(btn_center_X, btn_center_X);
    }

    private class LongPressRunnable implements Runnable {
        @Override
        public void run() {
            //启动动画
        }
    }

    //录制时的动画
    private class RecordRunnable implements Runnable {
        @Override
        public void run() {
            startRecordingAnimation();
        }
    }

    private String remindText = "";

    private void startRecordingAnimation() {
        btn_inside_color = COLOR_BG_ON_IDLE;
        btn_outside_color = Color.WHITE;
        btn_inside_radius = btn_after_inside_radius;
        record_anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                if (STATE_SELECTED == STATE_RECORD) {
                    progress = (float) animation.getAnimatedValue();
                    long remind = animation.getDuration() - animation.getCurrentPlayTime()+500;//补偿修正值
                    remindText = "" + remind / 1000 + "S";
                }
                invalidate();
            }
        });
        record_anim.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
                remindText = "" + 0 + "S";
                onStopOnRecord();
            }
        });
        record_anim.setInterpolator(new LinearInterpolator());
        record_anim.setDuration(durationAnim);
        record_anim.start();

    }

    private void startAnimation(float outside_start, float outside_end, float inside_start, float inside_end) {
        //动画-录制按钮
        ValueAnimator outside_anim = ValueAnimator.ofFloat(outside_start, outside_end);
        ValueAnimator inside_anim = ValueAnimator.ofFloat(inside_start, inside_end);
        outside_anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                btn_outside_radius = (float) animation.getAnimatedValue();
                STATE_Anim_playing = true;
                invalidate();
            }
        });
        outside_anim.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
                STATE_Anim_playing = false;
                if (STATE_SELECTED == STATE_RECORD) {
                    postDelayed(recordRunnable, 100);
                }
            }
        });
        inside_anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                btn_inside_radius = (float) animation.getAnimatedValue();
                invalidate();
            }
        });
        ValueAnimator color_anim = ValueAnimator.ofFloat(outside_start, outside_end);
        outside_anim.setDuration(100);
        inside_anim.setDuration(100);
        outside_anim.start();
        inside_anim.start();
    }

    private void captureAnimation(float left, float right) {
        ValueAnimator left_anim = ValueAnimator.ofFloat(btn_left_X, left);
        ValueAnimator right_anim = ValueAnimator.ofFloat(btn_right_X, right);
        left_anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                STATE_Anim_playing = true;
                btn_left_X = (float) animation.getAnimatedValue();
                invalidate();
            }

        });
        left_anim.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation, boolean isReverse) {
                STATE_Anim_playing = false;
                if (STATE_PENDING != null) {
                    if (STATE_PENDING != STATE_SELECTED) {
                        STATE_SELECTED = STATE_PENDING;
                        invalidate();
                        STATE_PENDING = null;
                    }
                }
            }
        });

        right_anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                STATE_Anim_playing = true;
                btn_right_X = (float) animation.getAnimatedValue();
                invalidate();
            }
        });
        right_anim.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation, boolean isReverse) {
                STATE_Anim_playing = false;
                if (STATE_PENDING != null) {
                    if (STATE_PENDING != STATE_SELECTED) {
                        STATE_SELECTED = STATE_PENDING;
                        invalidate();
                        STATE_PENDING = null;
                    }
                }
            }
        });
        left_anim.setDuration(200);
        right_anim.setDuration(200);
        left_anim.start();
        right_anim.start();
    }

    public void setCaptureListener(CaptureListener mCaptureListener) {
        this.mCaptureListener = mCaptureListener;
    }

    public interface CaptureListener {
        void capture();

        void cancel();//拍照点击返回

        void determine();//拍照的确定

        void quit();//关闭界面

        void record();

        void recordEnd();

        void getRecordResult();//录像点击确定

        void deleteRecordResult();//录像点击返回

        void scale(float scaleValue);
    }
}